import os
import random
import shutil

from moviepy import AudioFileClip, VideoFileClip
import pyJianYingDraft as draft

from combinations.config import OUTPUT_PATH, DRAFT_PATH
from combinations.conf import logger
from pyJianYingDraft import Font_type, trange, Text_style, Export_framerate, Export_resolution
import pandas as pd


# ==================== 工具函数 ====================

def load_files_from_dir(directory):
    """
    加载指定目录下的所有文件，并返回其全路径列表。

    Args:
        directory (str): 文件夹路径

    Returns:
        List[str]: 文件的全路径列表
    """
    logger.info(f"正在加载目录中的文件: {directory}")
    files = [os.path.join(directory, f) for f in os.listdir(directory)
             if os.path.isfile(os.path.join(directory, f))]
    logger.debug(f"共找到 {len(files)} 个文件")
    return files


def replace_bgm(script, bgm_file):
    """
    替换剪映草稿中的背景音乐素材。

    Args:
        script (draft.Script): 当前操作的脚本对象
        bgm_file (str): 新背景音乐文件路径
    """
    logger.info("开始替换 BGM...")
    bgm_material = draft.Audio_material(bgm_file)
    script.replace_material_by_name(material_name="if i got jesus.MP3", material=bgm_material)
    logger.info(f"替换【BGM】素材: if i got jesus.MP3 -> {bgm_file}")


def replace_voiceover(script, audio_path):
    """
    替换口播音频素材。

    Args:
        script (draft.Script): 当前操作的脚本对象
        audio_path (str): 新音频文件路径
    """
    logger.info("开始替换口播音频...")
    new_material = draft.Audio_material(audio_path)
    audio_track = script.get_imported_track(draft.Track_type.audio, index=0)
    script.replace_material_by_seg(track=audio_track, segment_index=0,
                                   material=new_material,
                                   handle_extend=[draft.Extend_mode.extend_tail])
    logger.info(f"替换【音频】素材: 口播音频.wav -> {audio_path}")


def replace_images(script, image_files):
    """
    替换剪映模板中的图片素材。

    Args:
        script (draft.Script): 当前操作的脚本对象
        image_files (List[str]): 图片文件路径列表
    """
    logger.info("开始替换图片素材...")
    original_names = [f"图片_{i}.png" for i in range(1, 21)]
    for idx, img_file in enumerate(image_files):
        new_material = draft.Video_material(img_file)
        script.replace_material_by_name(material_name=original_names[idx], material=new_material)
        logger.info(f"替换【图片】素材: {original_names[idx]} -> {img_file}")


def replace_cover(script, cover_file):
    """
    替换剪映模板中的封面图。

    Args:
        script (draft.Script): 当前操作的脚本对象
        cover_file (str): 封面图文件路径
    """
    logger.info("开始替换封面...")
    cover_material = draft.Video_material(cover_file)
    script.replace_material_by_name(material_name="封面.png", material=cover_material)
    logger.info(f"替换【封面】素材: 封面.png -> {cover_file}")


def import_subtitles(script, srt_path):
    """
    导入 SRT 字幕文件到视频轨道中。

    Args:
        script (draft.Script): 当前操作的脚本对象
        srt_path (str): SRT 字幕文件路径
    """
    logger.info("开始导入字幕...")
    try:
        text_segment = draft.Text_segment("文字", trange("0s", "10s"),
                                          font=Font_type.新青年体,
                                          border=draft.Text_border(width=30),
                                          style=Text_style(bold=True, size=12,
                                                           color=(1.0, 1.0, 1.0),
                                                           underline=False,
                                                           align=1, alpha=1.0))
        script.import_srt(srt_path, track_name="字幕2",
                          style_reference=text_segment,
                          clip_settings=draft.Clip_settings(transform_y=-0.5),
                          font_size=10)
        logger.info(f"成功导入SRT文件: {srt_path}")
    except Exception as e:
        logger.error(f"导入SRT失败: {e}", exc_info=True)


def crop_video(output_path, audio_duration, export_folder, combo_name):
    """
    根据音频时长裁剪视频。

    Args:
        output_path (str): 视频输出路径
        audio_duration (float): 音频时长（秒）
        export_folder (str): 输出目录
        combo_name (str): 任务名称标识符
    """
    logger.info("开始裁剪视频...")
    accelerated_audio_duration = audio_duration + 1
    video_clip = VideoFileClip(output_path)

    if video_clip.duration > accelerated_audio_duration:
        logger.info(f"视频时长 {video_clip.duration:.2f}s 超过音频时长 {accelerated_audio_duration:.2f}s，将进行裁剪")
        video_clip = video_clip.subclipped(0, accelerated_audio_duration)
        new_output_path = os.path.join(export_folder, "已剪辑", f"剪裁_{combo_name}.mp4")
        os.makedirs(os.path.dirname(new_output_path), exist_ok=True)
        video_clip.write_videofile(new_output_path, codec="libx264")
        logger.info(f"视频剪辑成功，保存路径为：{new_output_path}")
    else:
        logger.info("视频时长与音频匹配，无需裁剪")

    video_clip.close()


def delete_old_draft(folder_path, combo_name):
    """
    删除历史草稿文件夹。

    Args:
        folder_path (str): 草稿所在基础路径
        combo_name (str): 要删除的草稿名
    """
    full_path = os.path.join(folder_path, combo_name)
    logger.info(f"尝试删除历史草稿: {full_path}")
    if os.path.exists(full_path):
        shutil.rmtree(full_path)
        logger.info(f"✅ 已删除文件夹: {full_path}")
    else:
        logger.warning(f"⚠️ 文件夹不存在: {full_path}")


# ==================== 主流程 ====================

def jesus_template():
    """
    主函数：批量生成剪映视频并导出
    """

    # 初始化剪映项目配置
    logger.info("初始化剪映草稿模板...")
    draft_folder = draft.Draft_folder(DRAFT_PATH)

    # 设置资源路径
    home_page_dir = r"D:\模板3_耶稣涨粉-2\封面"
    bgm_dir = r"D:\模板3_耶稣涨粉-2\BGM"
    image_dir = r"D:\模板3_耶稣涨粉-2\图片_1"
    audio_dir = r"D:\模板3_耶稣涨粉-2\口播音频"
    srt_dir = r"D:\模板3_耶稣涨粉-2\SRT"
    base_folder = os.path.join(
        # LOCALAPPDATA 是 Windows 系统中的一个环境变量，表示当前用户的本地应用程序数据存储路径
        # C:\Users\<用户名>\AppData\Local
        os.getenv("LOCALAPPDATA"),
        "JianyingPro\\User Data\\Projects\\com.lveditor.draft"
    )

    # 加载资源文件
    logger.info("加载本地资源文件...")
    all_home_files = load_files_from_dir(home_page_dir)
    all_bgm_files = load_files_from_dir(bgm_dir)
    all_image_files = load_files_from_dir(image_dir)

    # 读取 Excel 数据
    logger.info("读取Excel数据...")
    excel_path = r"D:\模板3_耶稣涨粉-2\Jesus_null1.xlsx"
    columns_to_read = ['Number', 'Content', 'Vo_path']
    df = pd.read_excel(excel_path, usecols=columns_to_read)
    data_list = df.to_dict(orient='records')

    # 循环处理每条数据
    logger.info("开始批量生成视频任务...")
    for k, data in enumerate(data_list[:500]):
        combo_name = f"{k}_耶稣涨粉_模板_2"
        voice_file_name = os.path.basename(data['Vo_path'])
        srt_file_name = data['Content']

        logger.info(f"🚀 开始处理第 {k} 条任务")
        logger.info(f"音频文件: {voice_file_name} | 字幕文件: {srt_file_name}")

        # 创建脚本副本
        script = draft_folder.duplicate_as_template("模板3_耶稣涨粉-2", combo_name, allow_replace=True)
        logger.info(f"创建草稿副本: {combo_name}")

        # 替换 BGM
        replace_bgm(script, random.choice(all_bgm_files))

        # 替换口播音频
        new_audio_path = os.path.join(audio_dir, voice_file_name)
        replace_voiceover(script, new_audio_path)

        # 替换图片
        image_files = random.sample(all_image_files, 20)
        replace_images(script, image_files)

        # 替换封面
        replace_cover(script, all_home_files[k % len(all_home_files)])

        # 导入字幕
        srt_path = os.path.join(srt_dir, srt_file_name)
        if os.path.exists(srt_path):
            import_subtitles(script, srt_path)
        else:
            logger.warning(f"未找到字幕文件: {srt_file_name}")

        # 保存草稿
        script.save()
        logger.info("✅ 草稿保存完成")

        # 导出视频
        logger.info("🎬 开始导出视频")
        ctrl = draft.Jianying_controller()
        export_folder = os.path.join(OUTPUT_PATH, "耶稣涨粉-2")
        output_path = os.path.join(export_folder, f"{combo_name}.mp4")

        ctrl.export_draft(combo_name, output_path,
                          resolution=Export_resolution.RES_1080P,
                          framerate=Export_framerate.FR_24,
                          zi_mu=False,
                          kou_tu=False)
        logger.info(f"导出视频完成: {output_path}")

        # 裁剪视频
        logger.info("✂️ 开始裁剪视频")
        audio_clip = AudioFileClip(new_audio_path)
        audio_duration = audio_clip.duration
        audio_clip.close()
        crop_video(output_path, audio_duration, export_folder, combo_name)

        # 删除旧草稿
        delete_old_draft(base_folder, combo_name)

        logger.info(f"✅ 第 {k} 条任务处理完成\n")

    logger.info("🎉 全部任务已完成！")


if __name__ == "__main__":
    jesus_template()
